package org.knot.autojmx.example;

import java.lang.management.ManagementFactory;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.ReflectionException;

import org.knot.autojmx.AutoJMXHandler;
import org.knot.autojmx.api.AutoJMXAPI;
import org.knot.autojmx.spring.AutoJMXPostProcessor;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAutoJMX{

	private static String testjmx = "testjmx";

	private static String testjmx2 = "testjmx2";
	
	private static ClassPathXmlApplicationContext context  = new ClassPathXmlApplicationContext("test-spring-jmx.xml");

	private static MBeanServer server = ManagementFactory.getPlatformMBeanServer();

	/**
	 * 
	 * test main method
	 * 
	 * @param args
	 * @throws InterruptedException 
	 * @throws ReflectionException 
	 * @throws MBeanException 
	 * @throws InstanceNotFoundException 
	 * @throws AttributeNotFoundException 
	 */
	public static void main(String[] args) throws InterruptedException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException {
		
		TestJMXBean testjmx1=  (TestJMXBean) context.getBean(testjmx);
		TestJMXBean2 testjmx2=  (TestJMXBean2) context.getBean("testjmx2");
		AutoJMXPostProcessor autojmx=  (AutoJMXPostProcessor) context.getBean("autojmx");
		AutoJMXHandler hadndler = AutoJMXAPI.getHandlers().get(testjmx);
		if (null!= hadndler && hadndler.isRegistered())
		{
			ObjectInstance instance = hadndler.getInstance();
			System.out.println("print jmx bean's MBean info...");
			printMBeanInfo(instance.getObjectName(), testjmx);
			
			System.out.println();
			validateJMX(testjmx1, instance);
			
			System.out.println("call bean's setM_integer Method change property value...");
			testjmx1.setM_integer(2);
			
			validateJMX(testjmx1, instance);
			
			System.out.println("call jmx's setM_integer Method change property value...");
			invoke(instance.getObjectName(), "setM_integer", new Object[]{3},
		            new String[]{"int"}) ;
			
			validateJMX(testjmx1, instance);
			
		}
//		Thread.sleep(Long.MAX_VALUE);
		//销毁
		context.destroy();
	}
	
	//compare to pojoBean and jmxBean property
	public static  void validateJMX(TestJMXBean testjmx1, ObjectInstance instance) throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException
	{
		System.out.println("validate two method get property value...");
		System.out.println("bean value1："+ testjmx1.getM_integer());
		System.out.println("jmx  value2："+ getAttribute(instance.getObjectName(), "m_integer"));
//		org.junit.Assert.assertEquals(testjmx1.getM_integer(), getAttribute(instance.getObjectName(), "m_integer"));
		
	}
	
	//jmxBean get property value
	public static  Object getAttribute(ObjectName mbeanObjectName, String fieldName) throws AttributeNotFoundException,
		InstanceNotFoundException, MBeanException, ReflectionException {
	return  server.getAttribute(mbeanObjectName, fieldName);
	}
	
	//jmxBean call method  
	public static  void invoke(ObjectName mbeanObjectName, String methodName, Object[] params,
            String[] signature) throws InstanceNotFoundException, MBeanException,
		ReflectionException {
		server.invoke(mbeanObjectName, methodName, params, signature);
	}

	//print MBean info
	public static  void printMBeanInfo(ObjectName mbeanObjectName, String mbeanName) {
		MBeanInfo info = null;
		try {
			info = server.getMBeanInfo(mbeanObjectName);
		} catch (Exception e) {
			System.out.println("\t!!! Could not get MBeanInfo object for "
					+ mbeanName + " !!!");
			e.printStackTrace();
			return;
		}
		System.out.println("\nCLASSNAME: \t" + info.getClassName());
		System.out.println("\nDESCRIPTION: \t" + info.getDescription());
		System.out.println("\nATTRIBUTES");
		MBeanAttributeInfo[] attrInfo = info.getAttributes();
		if (attrInfo.length > 0) {
			for (int i = 0; i < attrInfo.length; i++) {
				System.out.println(" ** NAME: \t" + attrInfo[i].getName());
				System.out.println(" DESCR: \t" + attrInfo[i].getDescription());
				System.out.println(" TYPE: \t" + attrInfo[i].getType()
						+ "\tREAD: " + attrInfo[i].isReadable() + "\tWRITE: "
						+ attrInfo[i].isWritable());
			}
		} else
			System.out.println(" ** No attributes **");
		System.out.println("\nCONSTRUCTORS");
		MBeanConstructorInfo[] constrInfo = info.getConstructors();
		for (int i = 0; i < constrInfo.length; i++) {
			System.out.println(" NAME: \t" + constrInfo[i].getName());
			System.out.println(" DESCR: \t" + constrInfo[i].getDescription());
			System.out.println(" PARAM: \t"
					+ constrInfo[i].getSignature().length + " parameter(s)");
		}
		System.out.println("\nOPERATIONS");
		MBeanOperationInfo[] opInfo = info.getOperations();
		if (opInfo.length > 0) {
			for (int i = 0; i < opInfo.length; i++) {
				System.out.println(" NAME: \t" + opInfo[i].getName());
				System.out.println(" DESCR: \t" + opInfo[i].getDescription());
				System.out.println(" PARAM: \t"
						+ opInfo[i].getSignature().length + " parameter(s)");
			}
		} else
			System.out.println(" No operations ** ");
		System.out.println("\nNOTIFICATIONS");
		MBeanNotificationInfo[] notifInfo = info.getNotifications();
		if (notifInfo.length > 0) {
			for (int i = 0; i < notifInfo.length; i++) {
				System.out.println(" NAME: \t" + notifInfo[i].getName());
				System.out
						.println(" DESCR: \t" + notifInfo[i].getDescription());
			}
		}
	}
}
